package com.moarea.app.service.abst;

import com.moarea.app.service.inter.IFTPService;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;

/**
 * FTP文件服务处理抽象类
 * <p>
 * jizhong
 * <p>
 * 2017-09-20
 */
public abstract class AFTPService extends AHTTPService implements IFTPService {

    //临时参数 -- 存储当前FTP登录目标
    protected String FTP_IP;
    protected String FTP_PORT;
    private String FTP_USERNAME;
    private String FTP_PASSWORD;

    /**
     * FTP登录
     * <p>
     * jizhong
     * <p>
     * 2017-09-20
     *
     * @param ip       IP地址（不包含端口）
     * @param port     端口
     * @param username 用户名
     * @param password 密码
     * @return FTPClient
     */
    @Override
    public FTPClient ftpLogin(String ip, String port, String username, String password) {

        //重置FTP登录目标
        FTPClient ftpClient = new FTPClient();
        // 连接地址
        try {
            ftpClient.connect(ip, Integer.parseInt(port));
            return ftpClient.login(username, password) ? ftpClient : null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 设置目标FTP登录参数到临时数据中
     * <p>
     * <p>
     * jizhong
     * <p>
     * 2017-09-20
     *
     * @param ip       IP
     * @param port     端口
     * @param username 用户名
     * @param password 密码
     */
    @Override
    public void setTargetFTPLoginParam(String ip, String port, String username, String password) {
        this.FTP_IP = ip;
        this.FTP_PORT = port;
        this.FTP_USERNAME = username;
        this.FTP_PASSWORD = password;
    }

    /**
     * 下载FTP文件
     * <p>
     * * <p>
     * jizhong
     * <p>
     * 2017-09-20
     *
     * @param ftpClient FTP客户端对象
     * @param ftpPath   下载文件地址
     * @param localPath 本地保存地址
     * @param delOrNot  是否删除
     * @return 下载是否完成
     */
    @Override
    public String[] downloadFTPFiles(FTPClient ftpClient, String ftpPath, String localPath, boolean delOrNot) throws IOException {

        //设置Logger
        setLogger(AFTPService.class);

        FTPClient client = ftpClient.isConnected() ? ftpClient : ftpLogin(FTP_IP, FTP_PORT, FTP_USERNAME, FTP_PASSWORD);
        if (client == null) {
            logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->下载文件失败，FTP登录失败");
            return new String[]{};
        }

        //首先判断FTP响应是否正常
        if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
            client.disconnect();
            logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->未正常响应，请检查配置是否正确");
            return new String[]{};
        }

        logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->正常响应");

        // 设置文件传输的方式，如这里的二进制
        client.setFileType(FTPClient.BINARY_FILE_TYPE);
        // 切换到我们指定的文件目录
        client.changeWorkingDirectory(ftpPath);
        // 设置被动模式
        client.enterLocalPassiveMode();
        // 列举出所有的文件
        String[] ftpFileNames = client.listNames();
        logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->下载文件数量：" + ftpFileNames.length);
        //遍历处理文件到本地
        for (String fileName : ftpFileNames) {
            boolean saveResult = saveFTPFile(client, fileName, ftpPath, localPath, delOrNot);
            logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->文件保存->" + fileName + "->保存" + (saveResult ? "成功" : "失败"));
        }

        //处理完成之后 -->关闭FTP链接
        // 关闭FTPClient连接
        if (client.isConnected()) {
            client.logout();// 退出登录
            client.disconnect();
            logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->正常退出");
        }

        return ftpFileNames;
    }

    /**
     * 保存FTP文件到本地路径下
     * <p>
     * * <p>
     * jizhong
     * <p>
     * 2017-09-20
     *
     * @param ftpClient FTPClient对象
     * @param fileName  文件名称
     * @param ftpPath   FTP文件路径
     * @param localPath 本地地址
     * @param delOrNot  读取后是否删除
     * @throws IOException
     */
    @Override
    public boolean saveFTPFile(FTPClient ftpClient, String fileName, String ftpPath, String localPath, boolean delOrNot) throws IOException {

        //设置Logger
        setLogger(AFTPService.class);

        //检查目录是否存在，不存在则进行创建
        File dictionary = new File(localPath);
        if (!dictionary.exists()) {
            boolean createDirs = dictionary.mkdirs();
            if (createDirs) {
                logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->删除->" + fileName + "->文件夹创建成功");
            } else {
                logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->删除->" + fileName + "->文件夹创建失败，保存取消");
                return false;
            }
        }
        // 文件输出流
        OutputStream outputStream = new FileOutputStream(
                new File(localPath.replaceAll("\\\\", "/").concat("/").concat(fileName)));
        boolean readSuccess = ftpClient.retrieveFile(ftpPath.replace("\\\\", "/") + "/" + fileName, outputStream);
        if (readSuccess) {
            logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->读取文件->" + fileName + "->文件" + ("成功"));
            if (delOrNot) {
                //删除FTP文件
                boolean delResult = ftpClient.deleteFile(ftpPath.replace("\\\\", "/") + "/" + fileName);
                logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->删除->" + fileName + "->文件" + (delResult ? "成功" : "失败"));
            }
            return true;
        } else {
            logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->读取文件->" + fileName + "->文件" + ("失败"));
            return false;
        }
    }


    /**
     * 上传文件到FTP
     * <p>
     * * <p>
     * jizhong
     * <p>
     * 2017-09-20
     *
     * @param ftpClient FTPClient客户端对象
     * @param filename  文件名
     * @param filePath  本地文件地址
     * @param ftpPath   FTP保存路径
     * @return 是否成功
     */
    @Override
    public boolean uploadFTPFile(FTPClient ftpClient, String filename, String filePath, String ftpPath, boolean closeFinal) {

        //设置Logger
        setLogger(AFTPService.class);
        FTPClient client;
        try {

            client = ftpClient.isConnected() ? ftpClient : ftpLogin(FTP_IP, FTP_PORT, FTP_USERNAME, FTP_PASSWORD);
            if (client == null) {
                logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->上传文件失败，FTP登录失败");
                return false;
            }

            //首先判断FTP响应是否正常
            if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
                client.disconnect();
                logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->未正常响应，请检查配置是否正确");
                return false;
            }
            logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->正常响应");
            InputStream inputStream = new FileInputStream(new File(filePath.concat("/").concat(filename)));

            //4.指定写入的目录
            client.changeWorkingDirectory(ftpPath);

            //5.写操作
            client.setFileType(FTPClient.BINARY_FILE_TYPE);
            client.storeFile(filename, inputStream);

            inputStream.close();

            if (closeFinal) {
                //退出
                client.logout();
            }

            logger.info("FTP->" + FTP_IP + ":" + FTP_PORT + "->执行上传成功");

            return true;

        } catch (IOException e) {
            e.printStackTrace();

            return false;
        }
    }

    /**
     * 关闭FTP链接
     *
     * @param client FTP对象
     * @return 是否成功
     */
    @Override
    public boolean closeFtpConnection(FTPClient client) {
        try {
            return client == null || !client.isConnected() || client.logout();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
}
